If you are a software developer, you probably have been taught numerous times about the pointers in the college. Well, I have and each time I get the satisfaction of “hey, I know how pointers work!”. The funny thing is each time I come back to use it again, I am back to square one. The truth is it still confuses the hell out of me.
At the beginning of my career, I ended up programming in Perl about 10 years. As I am being soaked into Perl’s syntaxes and mechanisms, the concept of pointers in C grew to be even more confusing. There is the concept of the “references” in Perl which behaves very similar to the C pointers (references). However, at the end of the day, Perl’s references and C pointers are not exactly the same though.
The concept of pointers is really simple. You literally just have to remember this:
A pointer in C/C++ points to a memory location. That's pretty much it.
As usual, we can start with a very simple example in C:
What is happening above? The first line sets an integer variable called foo
to the value 1. Then the second line creates the integer pointer
called pFoo
which holds the memory location of foo
by calling &foo
. When you print out the content of the pointer, pFoo
in human-visible form, it would be something like:
As you see pFoo
contains the memory location of the variable foo
. How do we use the pointers then? Let’s add the third line to the example above.
This 3rd line might confuse a couple of people here because this could be appearing as setting 15 to the memory location. That is obviously not the case. *pFoo
means to follow the memory address and deal with the memory it points to. We should not be confused ourselves with,
We can see that the pFoo
is basically pointing to the foo
variable (residing in memory location 0x5100). This example is really all there are for C pointers.
However, we can make things more interesting to the problem by adding a pointer to a pointer. Let’s take a look at the new fourth line below:
So ppFoo is pointing to the memory location of pFoo which is a pointer to a variable pFoo. Now if you wanted to change the value of foo using ppFoo, you can simply call: **pFoo = 15;
, then the pointers will follow to the memory location it’s pointing at and eventually update the value of foo.
There are even more complexities you can add to the pointer flavour such as **ppFoo++
. Well, what does **ppFoo++
mean? ++ binds tighter than *, so this is equivalent to: *( *( ppFoo++ ) ). So you essentially broke your pointer to point at some random spot (probably nowhere, null). Your compiler will most likely bark at you if you try to do this seemingly unrealistic thing. What about this? ++**ppFoo
. This is nothing but fetching what’s contained in ppFoo and increment 1 to it. You will get the similar issue as the previous if you do this though, **++ppFoo
.
So why do we use pointers? Well, there are a couple of reasons:
There are other reasons to use pointers, but above 3 are biggest ones which I can think of.
To complete the topic of the pointers, references naturally follow for a discussion. Specifically, references are not available in C. The reference syntax is introduced in C++. However, references are worth a mention here as pointers and references are quite similar and go hand in hand. To place a definition of a reference:
A reference variable is essentially an alias which is another name for an already existing variable.
References work just like pointers with some syntactic sugar. int& rFoo
and int* pFoo
are essentially the same things, but you don’t have to dereference the reference. The reference basically acts as an ‘alias’ to a variable meaning unlike pointers, you do not always need the * in front of it to fetch/set the data.
We should remember that the references are required to always be pointing to a valid destination though. You cannot have an empty reference. Also, with a reference, you cannot change it to refer some other variable once it had been initialized. You can only choose what that reference would point to upon initializing it.